#include "StdAfx.h"
#include "DXCamara.h"
#include "BaseFunc.h"
#include "SampleGrabberCB.h"
#include <mtype.h>


CDXCamara::CDXCamara(void)
{
}

CDXCamara::~CDXCamara(void)
{
	m_pGrabber.Release();
}

BOOL CDXCamara::PlayFile(const char* inFile, HWND hWnd)
{
	HRESULT hr;

	RemoveAllFilters();
	// get whatever capture device exists
	//
	CComPtr< IBaseFilter > pCap;
	GetDefaultCapDevice( &pCap );
	if( !pCap )
		return FALSE;

	// add the capture filter to the graph
	//
	hr = m_pIGraphBuilder->AddFilter( pCap, L"Cap" );
	if( FAILED( hr ) )
		return FALSE;

	hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
	if( !m_pGrabber )
		return FALSE;

	CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
	// force it to connect to video, 24 bit
	//
	CMediaType VideoType;
	VideoType.SetType( &MEDIATYPE_Video );
	VideoType.SetSubtype( &MEDIASUBTYPE_RGB24 );
	hr = m_pGrabber->SetMediaType( &VideoType ); // shouldn't fail
	if( FAILED( hr ) )
		return FALSE;

	// add the grabber to the graph
	//
	hr = m_pIGraphBuilder->AddFilter( pGrabBase, L"Grabber" );
	if( FAILED( hr ) )
		return FALSE;

	// make a capture builder graph (for connecting help)
	//
	CComPtr< ICaptureGraphBuilder2 > pBuilder;
	hr = pBuilder.CoCreateInstance( CLSID_CaptureGraphBuilder2 );
	if( !pBuilder )
		return FALSE;

	hr = pBuilder->SetFiltergraph( m_pIGraphBuilder );

	if( FAILED( hr ) )
		return FALSE;


	// If there is a VP pin present on the video device, then put the 
	// renderer on CLSID_NullRenderer
	CComPtr<IPin> pVPPin;
	hr = pBuilder->FindPin(
		pCap, 
		PINDIR_OUTPUT, 
		&PIN_CATEGORY_VIDEOPORT, 
		NULL, 
		FALSE, 
		0, 
		&pVPPin);


	// If there is a VP pin, put the renderer on NULL Renderer
	CComPtr<IBaseFilter> pRenderer;
	if (S_OK == hr)
	{   
		hr = pRenderer.CoCreateInstance(CLSID_NullRenderer);    
		if (FAILED (hr))
		{
			return FALSE;
		}
		hr = m_pIGraphBuilder->AddFilter(pRenderer, L"NULL renderer");
		if (FAILED (hr))
		{
			return FALSE;
		}
	}

	hr = pBuilder->RenderStream(
		&PIN_CATEGORY_PREVIEW,
		&MEDIATYPE_Interleaved, 
		pCap, 
		pGrabBase, 
		pRenderer);
	if (FAILED (hr))
	{
		// try to render preview pin
		hr = pBuilder->RenderStream( 
			&PIN_CATEGORY_PREVIEW, 
			&MEDIATYPE_Video,
			pCap, 
			pGrabBase, 
			pRenderer);

		// try to render capture pin
		if( FAILED( hr ) )
		{
			hr = pBuilder->RenderStream( 
				&PIN_CATEGORY_CAPTURE, 
				&MEDIATYPE_Video,
				pCap, 
				pGrabBase, 
				pRenderer);
		}
	}

	if( FAILED( hr ) )
	{
		return FALSE;
	}

	// ask for the connection media type so we know how big
	// it is, so we can write out bitmaps
	//
	AM_MEDIA_TYPE mt;
	hr = m_pGrabber->GetConnectedMediaType( &mt );
	if ( FAILED( hr) )
	{
		return FALSE;
	}

	VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
	if(m_pSGCB)
	{
// 		m_pSGCB->SetOwner(GetParent(hWnd));
		m_pSGCB->SetWidth(vih->bmiHeader.biWidth);
		m_pSGCB->SetHeight(vih->bmiHeader.biHeight);
	}
	FreeMediaType( mt );

	// don't buffer the samples as they pass through
	//
	hr = m_pGrabber->SetBufferSamples( FALSE );

	// only grab one at a time, stop stream after
	// grabbing one sample
	//
	hr = m_pGrabber->SetOneShot( FALSE );

	// set the callback, so we can grab the one sample
	//
	hr = m_pGrabber->SetCallback( m_pSGCB, 1 );


// 	CComPtr< IBaseFilter > pMux;
// 	CComPtr< IFileSinkFilter > pSink;
// 	USES_CONVERSION;
// 
// 	hr = pBuilder->SetOutputFileName( &MEDIASUBTYPE_Avi,  T2W( inFile ), 
// 		&pMux, &pSink );
// 	if( FAILED( hr ) )
// 		return FALSE;
// 
// 	hr = pBuilder->RenderStream( &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
// 		pCap, NULL,pMux );
// 	if( FAILED( hr ) )
// 		return FALSE;

// 	hr = pBuilder->RenderStream( &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
// 		pCap, NULL, NULL );
// 	if( FAILED( hr ) )
// 		return FALSE;

	if(!SetDisplayWindow(hWnd))
	{
		return FALSE;
	}

	return Run();
}

BOOL CDXCamara::Pause()
{
	return Stop();
}



//////////////////////////////////////////////////////////////////////////
//class CDXVideoGrabber
//////////////////////////////////////////////////////////////////////////
CDXVideoGrabber::CDXVideoGrabber()
{

}

CDXVideoGrabber::~CDXVideoGrabber()
{
	m_pGrabber.Release();
}

BOOL CDXVideoGrabber::PlayFile(const char* inFile, HWND hWnd)
{
	RemoveAllFilters();

	HRESULT hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
	if( !m_pGrabber )
		return FALSE;

	CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
	// force it to connect to video, 24 bit
	//
	CMediaType VideoType;
	VideoType.SetType( &MEDIATYPE_Video );
	VideoType.SetSubtype( &MEDIASUBTYPE_RGB24 );
	hr = m_pGrabber->SetMediaType( &VideoType ); // shouldn't fail
	if( FAILED( hr ) )
		return FALSE;

	// add the grabber to the graph
	//
	hr = m_pIGraphBuilder->AddFilter( pGrabBase, L"Grabber" );
	if( FAILED( hr ) )
		return FALSE;

	RenderFile(inFile);

	AM_MEDIA_TYPE mt;
	hr = m_pGrabber->GetConnectedMediaType( &mt );
	if ( FAILED( hr) )
	{
		return FALSE;
	}

	VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
	if(m_pSGCB)
	{
		// 		m_pSGCB->SetOwner(GetParent(hWnd));
		m_pSGCB->SetWidth(vih->bmiHeader.biWidth);
		m_pSGCB->SetHeight(vih->bmiHeader.biHeight);
	}
	FreeMediaType( mt );

	// don't buffer the samples as they pass through
	//
	hr = m_pGrabber->SetBufferSamples( FALSE );

	// only grab one at a time, stop stream after
	// grabbing one sample
	//
	hr = m_pGrabber->SetOneShot( FALSE );

	// set the callback, so we can grab the one sample
	//
	hr = m_pGrabber->SetCallback( m_pSGCB, 1 );

	if(!SetDisplayWindow(hWnd))
	{
		return FALSE;
	}

	return Run();
}